#ifndef LEVEL_MANAGER_H
#define LEVEL_MANAGER_H

#include <string>
#include <vector>

#include "boost_filesystem.h"

#include "Level.h"
#include "LevelChangeSubject.h"
#include "Player.h"
#include "Portal.h"
#include "PortalSubject.h"

class Player;

// Class that manages every level in the game.
class LevelManager
: public LevelChangeSubject
, public PortalSubject
{
public:
    // Sets up the manager for use, but doesn't load the start level.
    static void initialise(std::string levelId, PlayerPtr player);
    static void cleanUp();
    static bool isInitialised();
    static LevelManager& get();

    // Loads the start level.
    //void loadStartLevel();

	LevelPtr getCurrentLevel() const;
	//CameraPtr getCamera() const;

    // Indicates whether the level is loading/fade is in a state where it is unsafe to render.
    // Every top level renderer (e.g. that has its Render() function called in Game.cpp)
    // must check this before rendering.
    bool isLevelLoading() const;

    void teleportPlayer(const Portal& portal);

    void update(float delta);
    void render(sf::RenderWindow& renderer);

    void readFile(std::string levelId, PlayerPtr player);
    void writeFile(std::string fileName) const;
    
    // The level manager is notified of attack hits because it
    // knows where NPCs are in the level and can determine if they are hit
    // and apply the damage.
    
    //ushort getBaseDepth() const;
private:
    static LevelManager instance;
	static bool initialised;

    LevelManager();
    virtual ~LevelManager();

	void setCurrentLevel();

    // - Calls level.readFile(fileName)
    // - registers the manager with the level for portal hits
    // - Adds the level to levels
    void loadLevel(Level& level, const boost_path& fileName);
        
    sf::Vector2f playerStartPos; // In pixels.

    // The current level.
	LevelPtr currentLevel;
    // The level that currentLevel is waiting to be changed to (if any).
    LevelPtr toLevel;
    // The portal that was hit to cause the level to be changed.
    Portal portalHit;

    PlayerPtr player;

    unsigned short baseRenderDepth;
	//CameraPtr levelCamera;
    
    bool fadeWaiting;
    //TimedCrossfade changedLevelsFade;
};

#endif